home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 …ember: Reference Library / Apple Developer Reference Library (December 1999) (Disk 1).iso / pc / technical documentation / develop / develop issue 28 / develop issue 28 code / merge tools / util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-05  |  7.6 KB  |  276 lines

  1. /* Support routines for Eclectus integration utilities.
  2.      Copyright (C) 1992-1996 Eclectus (D. John Anderson, Alan B. Harper).
  3.  
  4. This file is part of the Eclectus integration utilities.
  5.  
  6. Eclectus integration utilities are free software; you can redistribute
  7. it and/or modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 1, or
  9. (at your option) any later version.
  10.  
  11. Eclectus integration utilities is distributed in the hope that it
  12. will be useful, but WITHOUT ANY WARRANTY; without even the implied
  13. warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. See the GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with the Eclectus integration utilities; see the file COPYING.
  18. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge,
  19. MA 02139, USA.    */
  20.  
  21. #include "diff.h"
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #ifdef DF_MACHINE_MACINTOSH
  25.     #include <Types.h>
  26. #endif
  27.  
  28. #ifdef DF_MACHINE_NEXT
  29. /*
  30.     #include </usr/include/sys/param.h>
  31. */
  32. #endif
  33.  
  34. const char    *ECMessagessArray [MAX_ERROR_KIND + 1] = {
  35.     "Incompatible script version or bad script file",
  36.     "Bad script file or source path",
  37.     "Can't create the directory \"%s\"",
  38.     "Can't create the file \"%s\"",
  39.     "Can't open file %s",
  40.     "HASH ERROR!  The file may be corrupted.",
  41.     "Out of memory",
  42.     "You can't merge files or directories with the same name of different types",
  43.     "A non ASCII character was found",
  44.     "Path too long.  Shorten paths or eliminate directories",
  45.     "You must specify three or more paths: one root followed by two or more derived to merge into the root",
  46.     "You must specify three paths: one source path, one Difference script path and one destination path",
  47.     "You must specify two paths to compare",
  48.     "Unexpected IO Error on file \"%s\"",
  49.     "Unexpected option on command line: \"%s\""
  50.     };
  51.  
  52. /* Look at a hunk of edit script and report the range of lines in each file
  53.      that it applies to.    HUNK is the start of the hunk, which is a chain
  54.      of `struct change'.  The first and last line numbers of file 0 are stored in
  55.      *FIRST0 and *LAST0, and likewise for file 1 in *FIRST1 and *LAST1. 
  56.      Note that these are internal line numbers that count from 0.
  57.  
  58.      If no lines from file 0 are deleted, then FIRST0 is LAST0+1.
  59.  
  60.      Also set *DELETES nonzero if any lines of file 0 are deleted
  61.      and set *INSERTS nonzero if any lines of file 1 are inserted.
  62.      If only ignorable lines are inserted or deleted, both are
  63.      set to 0.    */
  64.  
  65. void
  66. AppendCharToPathName (char *destinationCharPtr, const char theChar)
  67. {
  68.     int destinationLength;
  69.  
  70.     destinationLength = strlen (destinationCharPtr);
  71.     if (destinationLength + 1 > FILENAME_MAX) {
  72.         fprintf (stderr, "%s%c\n", destinationCharPtr, theChar);
  73.         Error (PATH_TOO_LONG);
  74.     }
  75.     destinationCharPtr += destinationLength;
  76.     *destinationCharPtr++ = theChar;
  77.     *destinationCharPtr = '\0';
  78. }
  79.  
  80. void
  81. AppendStringToPathName (char *destinationCharPtr, const char *suffixCharPtr)
  82. {
  83.     int destinationLength;
  84.     int suffixLength;
  85.  
  86.     destinationLength = strlen (destinationCharPtr);
  87.     suffixLength = strlen (suffixCharPtr);
  88.     if (destinationLength + suffixLength > FILENAME_MAX) {
  89.         fprintf (stderr, "%s%s\n", destinationCharPtr, suffixCharPtr);
  90.         Error (PATH_TOO_LONG);
  91.     }
  92.     (void) memcpy (destinationCharPtr + destinationLength, suffixCharPtr, suffixLength + 1);
  93. }
  94.  
  95. void
  96. Error (int errorKind)
  97. {
  98.     ErrorWithStringArgument (errorKind, NULL);
  99. }
  100.  
  101. void
  102. ErrorWithStringArgument (int errorKind, const char *argumentStringPtr)
  103. {
  104.     if (argumentStringPtr == NULL)
  105.         fprintf (stderr, ECMessagessArray[errorKind], "Null Pointer");
  106.     else
  107.         fprintf (stderr, ECMessagessArray[errorKind], argumentStringPtr);
  108.     fprintf (stderr, ".\n");
  109.     exit (EXIT_FAILURE);
  110. }
  111.  
  112. /* Compare two lines.
  113.      Each line is described by a `struct line_def'.
  114.      Return 1 if the lines differ, like `bcmp'.  */
  115.  
  116. int
  117. line_cmp (struct line_def *s1, struct line_def *s2)
  118. {
  119.     register    char *t1, *t2;
  120.     char            savechar;
  121.  
  122.     t1 = s1->text;
  123.     t2 = s2->text;
  124.  
  125.     /* Alter the character following line 2 so it doesn't
  126.          match that following line 1.
  127.          (We used to alter the character after line 1,
  128.          but that caused trouble if line 2 directly follows line 1.)    */
  129.     savechar = s2->text[s2->length];
  130.     s2->text[s2->length] = (char) (s1->text[s1->length] + 1);
  131.  
  132.     /* Now find the first mismatch; this won't go past the
  133.          character we just changed.  */
  134.     #ifdef DF_COMPILER_MW
  135.         #pragma warn_possunwant off
  136.     #endif
  137.  
  138.     while (*t1++ == *t2++);
  139.  
  140.     #ifdef DF_COMPILER_MW
  141.         #pragma warn_possunwant reset
  142.     #endif
  143.     /* Undo the alteration.  */
  144.     s2->text[s2->length] = savechar;
  145.  
  146.     /* If the comparison stopped at the alteration,
  147.          the two lines are identical.  */
  148.     if (t2 == s2->text + s2->length + 1)
  149.         return 0;
  150.  
  151.     return (1);
  152. }
  153.  
  154. /* Print in a format somewhat like ed commands
  155.      except that each insert command states the number of lines it inserts.
  156.      This format is used for RCS.  */
  157.  
  158. void
  159. print_rcs_script (struct file_data *file0Ptr, struct file_data *file1Ptr)
  160. {
  161.     char                                        commandChar;
  162.     register struct change *hunkPtr;
  163.     struct line_def              *lastLinePtr;
  164.     struct line_def              *linePtr;
  165.     register int                        numberOfLines;
  166.  
  167.     hunkPtr = file1Ptr->scriptPtr;
  168.     if (hunkPtr == NULL) {
  169.         if (file0Ptr->buffer == NULL) {
  170.      /*
  171.         * File0 doesn't exist so add all of file 1.
  172.         */
  173.             numberOfLines = file1Ptr->buffered_lines;
  174.  
  175.             if (numberOfLines != 0) {
  176.                 commandChar = 'a';
  177.                 linePtr = file1Ptr->linbuf;
  178.                 lastLinePtr = linePtr + numberOfLines - 1;
  179.                 if (lastLinePtr->text [lastLinePtr->length - 1] != '\n')
  180.                     commandChar = 'A';
  181.                 printf ("%c0 %d\n", commandChar, numberOfLines);                        
  182.                 do {
  183.                     fwrite (linePtr->text, sizeof (char), linePtr->length, stdout);
  184.                     linePtr ++;
  185.                     numberOfLines --;
  186.                 } while (numberOfLines != 0);
  187.                 if (commandChar == 'A')
  188.                     putchar ('\n');
  189.             }
  190.         }
  191.     } else
  192.         while (hunkPtr)
  193.             {
  194.                 if (hunkPtr->deleted || hunkPtr->inserted) {
  195.  
  196.              /* For deletion, print just the starting line number from file 0
  197.                     and the number of lines deleted.    */
  198.                     if (hunkPtr->deleted)
  199.                         printf ("x%d %d\n", hunkPtr->line0 + 1, hunkPtr->deleted);            
  200.  
  201.              /* Take last-line-number from file 0 and # lines from file 1.    */
  202.                     numberOfLines = hunkPtr->inserted;
  203.                     if (hunkPtr->inserted != 0)
  204.                         {
  205.                             commandChar = 'a';
  206.                             linePtr = &file1Ptr->linbuf[hunkPtr->line1];
  207.                             lastLinePtr = linePtr + numberOfLines - 1;
  208.                             if (lastLinePtr->text [lastLinePtr->length - 1] != '\n')
  209.                                 commandChar = 'A';
  210.  
  211.                             printf ("%c%d %d\n", commandChar, hunkPtr->line0 + hunkPtr->deleted, numberOfLines);                    
  212.  
  213.                             /* Print the inserted lines.    */
  214.                             do {
  215.                                 fwrite (linePtr->text, sizeof (char), linePtr->length, stdout);
  216.                                 linePtr ++;
  217.                                 numberOfLines --;
  218.                             } while (numberOfLines != 0);
  219.                             if (commandChar == 'A')
  220.                                 putchar ('\n');
  221.                         }
  222.                 }
  223.                 hunkPtr = hunkPtr->link;
  224.          }
  225. }
  226.  
  227. void
  228. RemoveNameSuffix (char *namePtr)
  229. {
  230.     char *suffixPtr;
  231.  
  232.     suffixPtr = strrchr (namePtr, DIRECTORY_CHAR);
  233.     if (suffixPtr == NULL)
  234.         suffixPtr = namePtr;
  235.     *suffixPtr = '\0';
  236. }
  237.  
  238. /* malloc a block of memory, with fatal error message if we can't do it. */
  239.  
  240. void *
  241. xmalloc (size_t size)
  242. {
  243.     register void *value;
  244.  
  245.     /*
  246.      *  MPW realloc returns a memory error when a size of 0 is requested
  247.      */
  248.     if (size == 0)
  249.         size = 1;
  250.     value = malloc (size);
  251.  
  252.     if (value == NULL)
  253.         Error (MEMORY_ERROR);
  254.     return value;
  255. }
  256.  
  257. /* realloc a block of memory, with fatal error message if we can't do it. */
  258.  
  259. void *
  260. xrealloc (void *old, size_t size)
  261. {
  262.     register void *value;
  263.  
  264.     /*
  265.      *  MPW realloc returns a memory error when a size of 0 is requested
  266.      */
  267.     if (size == 0)
  268.         size = 1;
  269.     value = realloc (old, size);
  270.  
  271.     if (value == NULL)
  272.         Error (MEMORY_ERROR);
  273.     return value;
  274. }
  275.  
  276.